今天要來應用新的元件 RecyclerView:
使用之前必須到 Gradle Scripts > build.gradle (Module: app) > dependencies 加入使用相關 API,在新的一行按 Alt + Enter > 選擇圖二的 recyclerview。
接著請確定是否有產生如下的片段,若前方非 implementaion
請修正如下:
implementation 'com.android.support:recyclerview-v7:28.0.0'
此時畫面右上方會出現 Sync Now 字樣,請點選讓專案重新同步,稍待片刻後就完成了加入參照 API。
接續至專案的 Adapters 資料夾底下再新增一個 GroupRecycleAdapter Class。
在 GroupRecycleAdapter 中,編寫以下程式,接收的參數與先前的設計相同,不過因為這些參數其實都不會被更動到,所以依據 IDE 建議都修改宣告為 val
。完成建構子後,於此類別內建立一個 inner class
,名為 Holder
(類別的命名需首字大寫)。這個內部類別要接收 itemView
,並將值傳送到 RecyclerView.ViewHolder
,詳細撰寫方式如下:
class GroupRecycleAdapter(val context: Context, val groups: List<FoodGroup>) {
inner class Holder(itemView: View): RecyclerView.ViewHolder(itemView)
}
完成內部類別 Holder
後,接著在上層的 GroupRecycleAdapter
後方加入繼承 : RecyclerView.Adapter
抽象類別,繼承時需要指定上方建立的內部類別 Holder
,程式如下:
class GroupRecycleAdapter(val context: Context, val groups: List<FoodGroup>): RecyclerView.Adapter<GroupRecycleAdapter.Holder>()
繼承抽象方法後,我們必須實作成員,如同 Day 25 章節,透過 Alt + Enter > Implement members,選取所有成員,產生如下三段方法:
先從簡單的部分下手,將 getItemCount
實作出來:
override fun getItemCount(): Int {
return groups.count()
}
內部類別 Holder
加入兩個屬性來做之前 findView
的工作,另外建立一個 bindGroup()
方法,此方法負責將清單項目的圖片及文字指定到兩個屬性物件上。
inner class Holder(itemView: View): RecyclerView.ViewHolder(itemView) {
val groupImage: ImageView = itemView.findViewById(R.id.groupImage)
val groupName: TextView = itemView.findViewById(R.id.groupName)
fun bindGroup(group: FoodGroup, context: Context) {
val resourceId = context.resources.getIdentifier(group.image, "drawable", context.packageName)
groupImage.setImageResource(resourceId)
groupName.text = group.name
// 可多加此段程式以便追蹤
Log.v("Test", group.name)
}
}
回到三個需要實作的成員,剛已解決了一個,剩下的 onBindViewHolder
呼叫剛才設計的內部 bindGroup
方法,將指定的清單項目及 context
傳入。
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.bindGroup(groups[position], context)
}
第三個成員 onCreateViewHolder
要做的工作,是最早在普通版 Adapter 負責將自訂樣式讀取出來所使用的方法:
override fun onCreateViewHolder(parent: ViewGroup, position: Int): Holder {
val view = LayoutInflater
.from(context)
.inflate(R.layout.group_list_item, parent, false)
return Holder(view)
}
完成了 Adapter 的設計後,需要返回至 MainActivity 修改一下,可以看到 Line: 27 已經變成錯誤狀態,原因是在 View 版面上我們還沒變更成新的 RecyclerView。
切換到 activity_main.xml 中,將原本的 ListView
改成 android.support.v7.widget.RecyclerView
,如下圖所示:
同時也能調整一下排版方式,將 layout 都設為依照約束條件,ID 的部分也能重新命名。
重新命名編輯後按下 Enter 會出現以下視窗,可以將所有用到此 ID 的參考同步變更為新的名稱。
還沒完成,最後一個步驟需要到 MainActivity,在指定 adapter
之後,要多加一行指定 layoutMagager
,決定 View 的排列方式:
fun generateListView() {
adapter = GroupRecycleAdapter(this, DataService.groups)
groupRecyclerView.adapter = adapter
groupRecyclerView.layoutManager = LinearLayoutManager(this)
}
執行模擬機檢查一下!會發現小小的瑕疵,清單項目間格不見了,之前的設計方式失去效用,要修正這個問題須回到 group_list_item.xml 將 ConstraintLayout
高度設為 160dp
,groupImage
在之前的版面設計步驟已經設定過 150dp
,所以相差的 10dp
就會成為間格距離。
再次執行!讀者可以觀察 Logcat,會發現所有項目只會各執行一次讀取圖檔/名稱,捲軸的滑動效果也較順暢。下一章節會繼續介紹項目清單的功能,讓我們明天見。